- 廢話前言
終於來到 Scope !!!!!- 這邊預計會講的順序是 : lexical scope -> Closure -> Modules
在這邊你會學習到接下來不斷提到的東西 :
{ .. } Curly Braces
[] + {}; // "[object Object]"
// 這個是 coercion 型別轉換的例子 , 轉成 "" + "[object Object]" ==> "[object Object]"
{} + []; // 0
// 前面的 {} 其實沒有被讀到(empty block),所以是一元運算子的轉數字 +[] ==> 0
其他狀況自己看書 YDKJS ch5.md#contextual-rules
這邊之後我不太讀文件了,文件到這邊只是規範,具體實作就比較難理解。
(資質不好 QQ)
舉個書上例子
// var a; var b;
var a = 10
b = 2;
a = b + 2
可以去玩看看 JavaScript ast 產生器,圖像配合書,理解更快喔。
你可能在書上面看過這個段落
function foo(a) {
console.log( a ); // 2
}
foo( 2 );
Engine: 嗨 Scope, 我有一個 RHS reference 是 foo. 你有聽說過嗎?
Scope: Why yes, 我有. Compiler 在幾秒之前剛剛 declared 他. 他是一個 function. Here you go.
Engine: Great, thanks! OK, I'm executing foo.
Engine: 嗨, Scope, 我有一個 LHS reference 是 a, 你有聽說過嗎?
Scope: Why yes, 我有. Compiler 在幾秒之前剛剛 declared 他, 他是一個 formal parameter to foo. Here you go.
Engine: Helpful as always, Scope. Thanks again. Now, time to assign 2 to a.
Engine: 嗨, Scope, 抱歉打擾. 我需要一個 RHS look-up for console. 你有聽說過嗎?
Scope: No problem, Engine,沒關係 這是我應該做的. Yes, 我有 console. 他是內建的(built-in). Here ya go.
Engine: Perfect. Looking up log(..). OK, great, it's a function.
Engine: Yo, Scope. 你可以幫我找 RHS reference to a. 我想我還記得他, 不過我想二次確認。
Scope: You're right, Engine. 同一個 a , 他沒改變. Here ya go.
Engine: Cool. Passing the value of a, which is 2, into log(..).
...
看起來很ㄎㄧㄤ,明天再來詳細描述。
開始以前,請先想像 declaration 像是 可以塗顏色的小球(marble),
作用域(Scope) 像是有顏色的桶子,
然後 引擎(Engine) 負責玩丟球遊戲,把有顏色的桶子和球配對。
我們要做的就是模仿他們溝通,玩這個把一樣顏色的小球丟到一樣顏色的桶子的遊戲。
Kyle Simpson : 網路上可以找到最像的圖。
不過還有一件事要說 ...
一般常見的定義,會看到大家說 "dynamic" or "interpreted" languages。
但其實多數人會誤解像是 bash 一樣 一行一行執行,由上到下的 "interpreter"。
但是事實上,如同其他多數的 language-compiler, JavaScript 會執行以下階段
可以去玩看看 JavaScript ast 產生器,圖像配合書,理解更快喔。
Tokenizing/Lexing
Parsing
同上圖,這邊產生的 tree 結構叫做 "AST" (Abstract Syntax Tree).
這些步驟都是一直產生的,具體應用大家有寫過 JavaScript/TypeScript 應該很常用
語言伺服器通訊協定 - 中文
IntelliSense 也是用上述 Protocol
你可能發現一個規則,這些東西都是寫 code 才有用,真正上線都會移掉。
背後原因就是 AST 。
更細節的 AST 可以玩看看這個工具,不過我覺得上面那個就很夠了。
https://astexplorer.net/
這個比較偏向如果想自己寫 ESlint 規則
variable declaration can have multiple declarators
function 裡面有 block statement,block statement 可以放 expression statement 和 return statement,當然也可以放 variable declaration
identifier , experssion 有左右之分
通常左邊是 identifier,右邊是 experssion or literal
你應該想到了,我們常常說的 LHS、RHS 的 L、R 就是這邊的左右
但其實不是方向的「左」「右」,是取決於有沒有 target
有一點 ( a && b ) 運算子 或是 (a || b) 運算子 只在乎 a 的味道。
Code-Generation : bytecode。
(有問題或是不清楚的地方,或是有其他資源可以補充給我~)
球和桶子的遊戲
如果還不能接受 JavaScript 會提前 parse,多玩一下上面的 AST,找資料理解一下怎麼產生的。
還沒有 bytecode
,但我們已經建立好 lexical environment 了 (reference: EC)。逐行執行
。JavaScript 是 interpreter
這個很容易誤解的說法用的名詞(所以你不要
誤認
JavaScript 是 interprete, JavaScript 會提前 parsed AST)
你可以查文件(ECMA-262, 10th edition, June 2019),Hoisting 這個字並沒有任何解釋。